package com.danguo.happymonkey;

import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;

import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.opengl.GLES20;
import android.opengl.GLSurfaceView;
import android.opengl.GLUtils;
import android.opengl.Matrix;
import android.util.Log;

public class Button {

   private static final int BYTES_PER_FLOAT = 4;
   private static final int POS_DATA_SIZE = 3;
   private static final int POS_OFFSET = 0;
   
   /** Store our model data in a float buffer. */
   private final FloatBuffer thePoint;
   private int[] theTextures;
   private float[] theModelMatrix = new float[16];
   private float[] theCoords = new float[4];
   private int theBaseMap;
   private int theMVPMatrixHandle;
   private int theProgramHandle;
   private int thePositionHandle;
   
   final String vertexShader = 
	         "uniform mat4 u_MVPMatrix; " + // A constant
	         "attribute vec4 a_Position;" + // Per-vertex position info we will pass in.
	        // "attribute vec2 aTextureCoord;" +
	        // "varying vec2 vTextureCoord;" +
	         "void main()" + 
	         "{" + 
	            "gl_PointSize = 45.0;" + 
	            "gl_Position = u_MVPMatrix*a_Position;" +
	         //   "vTextureCoord = aTextureCoord;" +
	         "}";
   final String fragmentShader = 
	         "precision mediump float;" + 
	        // "varying vec2 vTextureCoord;" +
	        // "uniform sampler2D sTexture;" +
	         "uniform sampler2D u_baseMap;" +
	         "void main()" +
	         "{" +
	            "gl_FragColor = texture2D(u_baseMap, gl_PointCoord);" +
	            //"gl_FragColor = texture2D(sTexture, vTextureCoord);" +
	         "}";
   
	public Button( GLSurfaceView aContext )
	{
		
	      theCoords = {};
	      thePoint = ByteBuffer.allocateDirect(theCoords.length * BYTES_PER_FLOAT)
	                           .order(ByteOrder.nativeOrder()).asFloatBuffer();

	      thePoint.put(theCoords).position(0);
	      Matrix.setIdentityM( theModelMatrix, 0 );
	      
	      theProgramHandle = createProgram(vertexShader, fragmentShader);
	      
	      // Set program handles. These will later be used to pass in values to the
	      // program.
	      theMVPMatrixHandle = GLES20.glGetUniformLocation( theProgramHandle,
	            "u_MVPMatrix" );
	      
	      thePositionHandle = GLES20.glGetAttribLocation( theProgramHandle, "a_Position" );
	      checkGlError("glGetAttribLocation aPosition");
	      if (thePositionHandle == -1) {
	         throw new RuntimeException("Could not get attrib location for aPosition");
	      }      
	      
	      theBaseMap = GLES20.glGetUniformLocation(theProgramHandle, "u_baseMap");
	      checkGlError("glGetUniformLocation uBaseMap");
	      
	      Log.d("Utils", "Loadtexture");
	      theTextures = new int[1];
	      GLES20.glGenTextures(2, theTextures, 0);
	      Bitmap img = BitmapFactory.decodeResource(aContext.getResources(), R.drawable.roundel);
	      assignTexture( img, theTextures, 0 );
	      img.recycle();
	}
	
	public draw()
	{
		
	}
	
	
   private void assignTexture( Bitmap anImg, int[] aTextureArray, int anIndex )
   {
      GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, aTextureArray[anIndex]);
      GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_LINEAR);
      GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_LINEAR);
      GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_S,
            GLES20.GL_CLAMP_TO_EDGE);
      GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_T,
            GLES20.GL_CLAMP_TO_EDGE);
      GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, anImg, 0);
      Log.d("LoadTexture", "Loaded texture"+":H:"+anImg.getHeight()+":W:"+anImg.getWidth());
      checkGlError( "Load Texture " + anIndex );
   }
/*******************************UTILITY METHODS**********************************
   
   /**
    * Loads and compiles a shader
    * @param shaderType integer from GLES20 representing the type of shader
    * @param source the C code describing the shader
    * @return the handle to the compiled shader
    */
   private int loadShader(int shaderType, String source) {
      int shader = GLES20.glCreateShader(shaderType);
      if (shader != 0) {
          GLES20.glShaderSource(shader, source);
          GLES20.glCompileShader(shader);
          int[] compiled = new int[1];
          GLES20.glGetShaderiv(shader, GLES20.GL_COMPILE_STATUS, compiled, 0);
          if (compiled[0] == 0) {
              Log.e("GLES20Points", "Could not compile shader " + shaderType + ":");
              Log.e("GLES20Points", GLES20.glGetShaderInfoLog(shader));
              GLES20.glDeleteShader(shader);
              shader = 0;
          }
      }
      return shader;
  }
   
   /**
    * Combines vertex and fragment shaders into a compiled program
    * @param vertexSource the C code describing the vertex shader
    * @param fragmentSource the C code describing the fragment shader
    * @return a handle to the compiled program
    */
   private int createProgram(String vertexSource, String fragmentSource) {
         int vertexShader = loadShader(GLES20.GL_VERTEX_SHADER, vertexSource);
         if (vertexShader == 0) {
             return 0;
         }

         int pixelShader = loadShader(GLES20.GL_FRAGMENT_SHADER, fragmentSource);
         if (pixelShader == 0) {
             return 0;
         }

         int program = GLES20.glCreateProgram();
         if (program != 0) {
             GLES20.glAttachShader(program, vertexShader);
             checkGlError("glAttachVShader");
             GLES20.glAttachShader(program, pixelShader);
             checkGlError("glAttachFShader");
             GLES20.glLinkProgram(program);
             int[] linkStatus = new int[1];
             GLES20.glGetProgramiv(program, GLES20.GL_LINK_STATUS, linkStatus, 0);
             if (linkStatus[0] != GLES20.GL_TRUE) {
                 Log.e("GLES20Points", "Could not link program: ");
                 Log.e("GLES20Points", GLES20.glGetProgramInfoLog(program));
                 GLES20.glDeleteProgram(program);
                 program = 0;
             }
         }
         return program;
     }
   
   /**
    * Checks GL for errors
    * @param op String to send to the log if an error is found.
    */
   private void checkGlError(String op) {
      int error;
      while ((error = GLES20.glGetError()) != GLES20.GL_NO_ERROR) {
          Log.e("GLES20Points", op + ": glError " + error);
          throw new RuntimeException(op + ": glError " + error);
      }
  }
}
